/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonebooksharing.android.util;

import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Contacts;
import android.provider.Contacts.Phones;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.phonebooksharing.android.R;
import com.phonebooksharing.android.async.SendTextMessageTask;
import com.phonebooksharing.dto.GenericTransferDTO;
import com.phonebooksharing.dto.friend.ContactItem;
import com.phonebooksharing.dto.msg.TextMessageItem;

public class GeneralUtils {
    /**
     * Sends an intent to create a new calendar event by prepopulating the Add Event UI. 
     * Older versions of the system have a bug where the event title will not be filled out.
     * 
     * @param summary
     *            A description of the event
     * @param start
     *            The start time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z'
     * @param end
     *            The end time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z'
     */
    public static final void addCalendarEvent(Context c, String summary, String start, String end) {
        Intent i = new Intent(Intent.ACTION_EDIT);
        i.setType("vnd.android.cursor.item/event");
        i.putExtra("beginTime", calculateMilliseconds(start));
        if (start.length() == 8) {
            i.putExtra("allDay", true);
        }
        i.putExtra("endTime", calculateMilliseconds(end));
        i.putExtra("title", summary);
        c.startActivity(i);
    }

    private static long calculateMilliseconds(String when) {
        if (when.length() == 8) {
            // Only contains year/month/day
            DateFormat format = new SimpleDateFormat("yyyyMMdd");
            Date date = format.parse(when, new ParsePosition(0));
            return date.getTime();
        } else {
            // The when string can be local time, or UTC if it ends with a Z
            DateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
            Date date = format.parse(when.substring(0, 15), new ParsePosition(0));
            long milliseconds = date.getTime();
            if (when.length() == 16 && when.charAt(15) == 'Z') {
                Calendar calendar = new GregorianCalendar();
                int offset = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET));
                milliseconds += offset;
            }
            return milliseconds;
        }
    }
    
    public static long getGmtTimeInMilis() {
        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
        return cal.getTimeInMillis();
    }
    
    public static long calculateGmtTimeInMilis(long gmtTimeInMilis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(gmtTimeInMilis);
        int offset = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET));
        return calendar.getTimeInMillis() + offset;
    }
    
    public static String getLengthByMilis(long milis) {

        int duration = (int) milis / 1000;
        int h = duration / 3600;
        int m = (duration - h * 3600) / 60;
        int s = duration - (h * 3600 + m * 60);
        if (h == 0) {
            return zeroPad(m, 2) + ":" + zeroPad(s, 2);
        } else {
            return zeroPad(h, 2) + ":" + zeroPad(m, 2) + ":" + zeroPad(s, 2);
        }
    }
    
    public static final String zeroPad(int inValue, int inMinDigits) {
        String val = String.valueOf(inValue);

        if (val.length() < inMinDigits) {
            char[] buf = new char[inMinDigits];

            for (int i = 0; i < inMinDigits; i++)
                buf[i] = '0';

            val.getChars(0, val.length(), buf, inMinDigits - val.length());
            val = new String(buf);
        }
        return val;
    }

    // public static final void addContact(Context c, String[] names, String[] phoneNumbers, String[] emails, String note, String address, String org, String title) {
    //
    // Intent intent = new Intent(Contacts.Intents.Insert.ACTION, Contacts.People.CONTENT_URI);
    // putExtra(intent, Contacts.Intents.Insert.NAME, names);
    //
    // int phoneCount = Math.min((phoneNumbers != null) ? phoneNumbers.length : 0, Contents.PHONE_KEYS.length);
    // for (int x = 0; x < phoneCount; x++) {
    // putExtra(intent, Contents.PHONE_KEYS[x], phoneNumbers[x]);
    // }
    //
    // int emailCount = Math.min((emails != null) ? emails.length : 0, Contents.EMAIL_KEYS.length);
    // for (int x = 0; x < emailCount; x++) {
    // putExtra(intent, Contents.EMAIL_KEYS[x], emails[x]);
    // }
    //
    // putExtra(intent, Contacts.Intents.Insert.NOTES, note);
    // putExtra(intent, Contacts.Intents.Insert.POSTAL, address);
    // putExtra(intent, Contacts.Intents.Insert.COMPANY, org);
    // putExtra(intent, Contacts.Intents.Insert.JOB_TITLE, title);
    // launchIntent(intent);
    // }

    public static final void shareByEmail(Context c, String contents) {// TODO: localize-me
    // sendEmailFromUri("mailto:", c.getString(R.string.msg_share_subject_line), contents);
        sendEmailFromUri(c, "mailto:", "Sharing this with you", contents);
    }

    public static final void sendEmail(Context c, String address, String subject, String body) {
        sendEmailFromUri(c, "mailto:" + address, subject, body);
    }
    
    public static final void sendEmail(Activity c, long personID, String subject, String body) {
        Cursor cu = c.managedQuery( 
                Contacts.ContactMethods.CONTENT_EMAIL_URI, 
                new String[] { 
                    Contacts.ContactMethods.DATA, 
                }, Contacts.ContactMethods.PERSON_ID + "=?", 
                new String[] {"" + personID}, 
                Contacts.ContactMethods.ISPRIMARY + " DESC"); 
        if(cu != null && cu.moveToFirst()) {
            sendEmailFromUri(c, "mailto:" + cu.getString(0), subject, body);
        }
    }

    public static final void sendEmailFromUri(Context c, String uri, String subject, String body) {
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
        putExtra(intent, "subject", subject);
        putExtra(intent, "body", body);
        c.startActivity(intent);
    }

    public static final void shareBySMS(Context c, String contents) {
        sendSMSFromUri(c, "smsto:", "Sharing this with you" + ":\n" + contents);
    }

    public static final void sendSMS(Context c, String phoneNumber, String body) {
        sendSMSFromUri(c, "smsto:" + phoneNumber, body);
    }

    public static final void sendSMS(Activity c, long personID, String body) {
        Cursor cu = c.managedQuery( 
                Phones.CONTENT_URI, 
                new String[] { 
                    Phones.NUMBER, 
                }, Phones.PERSON_ID + "=?", 
                new String[] {"" + personID}, 
                Phones.ISPRIMARY + " DESC"); 
        if(cu != null && cu.moveToFirst()) {
            sendSMSFromUri(c, "smsto:" + cu.getString(0), body);
        }
    }
    
    public static final void sendSMSFromUri(Context c, String uri, String body) {
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
        putExtra(intent, "sms_body", body);
        // Exit the app once the SMS is sent
        intent.putExtra("compose_mode", true);
        c.startActivity(intent);
    }

    public static final void sendMMS(Context c, String phoneNumber, String subject, String body) {
        sendMMSFromUri(c, "mmsto:" + phoneNumber, subject, body);
    }

    public static final void sendMMSFromUri(Context c, String uri, String subject, String body) {
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
        // The Messaging app needs to see a valid subject or else it will treat this an an SMS.
        if (subject == null || subject.length() == 0) {
            putExtra(intent, "subject", "Hi There");// TODO: localize-me
        } else {
            putExtra(intent, "subject", subject);
        }
        putExtra(intent, "sms_body", body);
        intent.putExtra("compose_mode", true);
        c.startActivity(intent);
    }

    public static final void dialPhone(Context c, String phoneNumber) {
        c.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
    }

    public static final void dialPhoneFromUri(Context c, String uri) {
        c.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(uri)));
    }
    
    public static final void startIM(Context c, String email) {
        try {
            c.startActivity(new Intent(Intent.ACTION_SENDTO, Uri.parse("imto://gtalk/" + email)));
        } catch(ActivityNotFoundException a) {
            Toast.makeText(c, "We're sorry but it seems that you don't have an IM client!", Toast.LENGTH_LONG).show();
        }
    }

    public static final void openMap(Context c, String geoURI) {
        c.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(geoURI)));
    }

    /**
     * Do a geo search using the address as the query.
     * 
     * @param address
     *            The address to find
     * @param title
     *            An optional title, e.g. the name of the business at this address
     */
    public static final void searchMap(Context c, String address, String title) {
        String query = address;
        if (title != null && title.length() > 0) {
            query = query + " (" + title + ")";
        }
        c.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + Uri.encode(query))));
    }

    public static final void getDirections(Context c, double fromLat, double fromLng, double toLat, double toLng) {
        final String sAddr  = fromLat + "," + fromLng;//source address
        final String dAddr  = toLat + "," + toLng;//destination address
        final String mapURL = String.format("http://maps.google." + getCountryTLD() + "/maps?f=d&saddr=%s&daddr=%s", sAddr, dAddr);
        c.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mapURL)));
    }

    public static final void openURL(Context c, String url) {
        if(!url.startsWith("http://")) {
            url = "http://" + url;
        }
        c.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
    }

    public static final void webSearch(Context c, String query) {
        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
        intent.putExtra("query", query);
        c.startActivity(intent);
    }

    private static final String DEFAULT_TLD = "com";
    private static final Map<Locale, String> GOOGLE_COUNTRY_TLD;
    static {
        GOOGLE_COUNTRY_TLD = new HashMap<Locale, String>(13);
        GOOGLE_COUNTRY_TLD.put(Locale.CANADA, "ca");
        GOOGLE_COUNTRY_TLD.put(Locale.CHINA, "cn");
        GOOGLE_COUNTRY_TLD.put(Locale.FRANCE, "fr");
        GOOGLE_COUNTRY_TLD.put(Locale.GERMANY, "de");
        GOOGLE_COUNTRY_TLD.put(Locale.ITALY, "it");
        GOOGLE_COUNTRY_TLD.put(Locale.JAPAN, "co.jp");
        GOOGLE_COUNTRY_TLD.put(Locale.KOREA, "co.kr");
        GOOGLE_COUNTRY_TLD.put(Locale.TAIWAN, "de");
        GOOGLE_COUNTRY_TLD.put(Locale.UK, "co.uk");
    }

    /**
     * @return country-specific TLD suffix appropriate for the current default locale (e.g. "co.uk" for the United Kingdom)
     */
    public static String getCountryTLD() {
        Locale locale = Locale.getDefault();
        if (locale == null) {
            return DEFAULT_TLD;
        }
        String tld = GOOGLE_COUNTRY_TLD.get(locale);
        if (tld == null) {
            return DEFAULT_TLD;
        }
        return tld;
    }

    private static void putExtra(Intent intent, String key, String value) {
        if (value != null && value.length() > 0) {
            intent.putExtra(key, value);
        }
    }
    
    public static void postTextMessageDialog(final Activity cx, String initialText, final ContactItem ci) {
        LayoutInflater factory = LayoutInflater.from(cx);
        final View postText = factory.inflate(R.layout.post_text, null);
        final Dialog myself = new AlertDialog.Builder(cx)
                      .setTitle("Enter your message")
                      .setView(postText)
                      .create();

        ((TextView)postText.findViewById(android.R.id.text1)).setText(initialText);
        postText.findViewById(android.R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                myself.dismiss();
            }
        });
        postText.findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TextMessageItem txtMsg = new TextMessageItem();
                final EditText title = (EditText)postText.findViewById(android.R.id.text1),
                               text  = (EditText)postText.findViewById(android.R.id.text2);
                txtMsg.title = title.toString();
                txtMsg.text  = text.toString();
                txtMsg.when  = GeneralUtils.getGmtTimeInMilis();
                if(ci != null) {
                    txtMsg.contactDeviceID = ci.andID;
                    txtMsg.type            = TextMessageItem.TEXT_PRIVATE;
                } else {
                    txtMsg.type            = TextMessageItem.TEXT_SHOUT;
                }
                
                GenericTransferDTO g = new GenericTransferDTO();
                g.authItem = Global.authItem;
                g.simpleItem = txtMsg;
                g.simpleID = 1L;
                
                new SendTextMessageTask(cx, String.format(Global.MESSAGE_SERVLET_URL, "cm" /*ac*/, "b" /*t*/, "" /*q*/, "" /*mt*/), g, false).execute();
                myself.dismiss();
            }
        });
        myself.show();
    }
}
